﻿using System;
using System.Linq;
using System.Reactive.Linq;

namespace CompositionalAudio
{
    public interface IStereoSource:IDisposable
    {
        IObservable<double> ChannelLeft { get; }
        IObservable<double> ChannelRight { get; }
    }

    public static class IStereoSourceExtentions
    {

        public static IObservable<byte[]> ToAudioSignal(this IStereoSource data, int buffersize, int SampleSize)
        {
            Func<double,byte[]> ExtractSample = null;
            switch (SampleSize)
            {
                case 32:
                    ExtractSample = (b) => 
                    { 
                        return BitConverter.IsLittleEndian ? 
                                                BitConverter.GetBytes((Int32)b)
                                                            .ToArray()
                                                            .Reverse()
                                                            .ToArray() : 
                                                BitConverter.GetBytes((Int32)b); 
                    };
                    break;
                case 16:
                    ExtractSample = (b) =>
                    {
                        return !BitConverter.IsLittleEndian ?
                                               BitConverter.GetBytes((Int16)b)
                                                           .ToArray()
                                                           .Reverse()
                                                           .ToArray() :
                                               BitConverter.GetBytes((Int16)b);
                    };
                    break;
            }
            return data.ChannelLeft                                                     //convert back to s,s,s rather than s[],s[],s[]
                        .Zip(data.ChannelRight, (ls, rs) => 
                            {
                                byte[] sig = ExtractSample(ls).Concat(ExtractSample(rs)).ToArray();
                                return sig;
                            })    //one sample from each channel
                        .SelectMany(samps => samps)                                     //convert to samples array l,r,l,r,l
                        .Buffer(buffersize)                                             //buffer samplerate*channels*2 seconds
                        .Select(x => x.ToArray());                                      // to observable of chunks


            //return data.ChannelLeft.SelectMany(x => x)                                                    //convert back to s,s,s rather than s[],s[],s[]
            //            .Zip(data.ChannelRight.SelectMany(y => y), (ls, rs) => new double[] { ls, rs })   //one sample from each channel
            //            .SelectMany(samps => samps)                                                       //convert to samples array l,r,l,r,l
            //            .Buffer(buffersize)                                                               //buffer samplerate*channels*2 seconds
            //            .Select(x => x.ToArray());                                                        // to observable of chunks
        }
    }
}
